﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LudeonTK;
using RimWorld;
using Verse;
using Verse.Noise;

namespace ARMIR
{
    public class HediffComp_familyRosmontis : HediffComp {
        public HediffCompProperties_familyRosmontis Props => (HediffCompProperties_familyRosmontis)props;
        private int gapFamilyCheck;
        private int gapMemoryChange;
        private int gapBookRead;
        private int gapMoodChange;
        private int recordEachDay; //每日记录
        private List<string> limitMeetEachDay;//每天可从家人处获得心情增益限制
        public List<string> rememberFamily;
        public int memoryRecordTimes; //记忆在玩家阵营度过的天数
        private int gapForget;
        private int gapNewFamily;
        
        public override void CompPostMake()
        {
            base.CompPostMake();
            gapFamilyCheck = 0;
            gapMemoryChange = 0;
            gapBookRead = 0;
            rememberFamily = new List<string>();
            limitMeetEachDay = new List<string>();
            recordEachDay = GenDate.DaysPassed;
            memoryRecordTimes = 0;
            gapMoodChange = 0;
        }
        public override void CompExposeData()
        {
            base.CompExposeData();
            Scribe_Values.Look(ref gapFamilyCheck, "gapFamilyCheck", 0);
            Scribe_Values.Look(ref gapMemoryChange, "gapMemoryChange", 0);
            Scribe_Values.Look(ref gapBookRead, "gapBookRead", 0);
            Scribe_Values.Look(ref gapMoodChange, "gapMoodChange", 0);
            Scribe_Values.Look(ref gapForget, "gapForget", 0);
            Scribe_Values.Look(ref recordEachDay, "recordEachDay", GenDate.DaysPassed);
            Scribe_Collections.Look(ref rememberFamily, "rememberFamily", LookMode.Value);
            Scribe_Collections.Look(ref limitMeetEachDay, "limitMeetEachDay", LookMode.Value);
            Scribe_Values.Look(ref memoryRecordTimes, "memoryRecordTimes", 0);
            

            // 确保列表在加载时不为 null
            if (Scribe.mode == LoadSaveMode.LoadingVars && rememberFamily == null)
            {
                rememberFamily = new List<string>();
            }
            if (Scribe.mode == LoadSaveMode.LoadingVars && limitMeetEachDay == null)
            {
                limitMeetEachDay = new List<string>();
            }
        }
        public override void CompPostTick(ref float severityAdjustment)
        {
            base.CompPostTick(ref severityAdjustment);
            if (parent.pawn == null || parent.pawn.Map == null) { 
                return;
            }
            float distanceToCell = parent.pawn.Position.DistanceTo(parent.pawn.Map.Center);
            float howMuchToCell = distanceToCell / (parent.pawn.Map.Size.x / 2);
            if (parent.pawn.Downed || howMuchToCell > 0.9f)
            {
                return;
            }
            gapFamilyCheck++;
            if (gapFamilyCheck > 100) {
                gapFamilyCheck = 0;
                gapMemoryChange++;
                gapBookRead++;
                gapMoodChange++;
                gapNewFamily++;
                if (GenDate.DaysPassed != recordEachDay) {
                    recordEachDay = GenDate.DaysPassed;
                    limitMeetEachDay.Clear();
                    recordOnNoteEachDay();
                }
                hardRe();
                //ILog();
            }
            if (gapMoodChange > 8) {
                gapMoodChange = 0;
                moodChangeByFamily();
            }
            if (gapMemoryChange > 100) {
                gapMemoryChange = 0;
                familyNumberForget();
            }
            if (gapBookRead > 10) {
                gapBookRead = 0;
                readBook();
            }
            if (gapNewFamily > 200) {
                gapNewFamily = 0;
                haveNewFamilyNumber();
            }
            gapForget--;
            if (gapForget < 0)
            {
                Forget();
                gapForget = Props.gapForget;
            }
        }
        /// <summary>
        /// 检查以使Rosmontis认定新的家人
        /// </summary>
        private void haveNewFamilyNumber() {
            //parent.pawn.needs.mood.thoughts.memories.TryGainMemory();
            //判定前提：迷迭香未死亡
            //判定认定新的家人，needs：被认定者必须：在迷迭香的视野范围内，与迷迭香处于同一个阵营中
            
            if (!parent.pawn.Dead) { 
                //周围的人
                List<Pawn> probalyFamily = parent.pawn.Map.mapPawns.AllHumanlikeSpawned.Where(p => 
                p.Position.DistanceTo(parent.pawn.Position) < 7 //距离迷迭香足够近
                && p.Faction == parent.pawn.Faction //同阵营
                && !p.HostileTo(parent.pawn) // 不敌对（）不知道是不是真的需要检测这一块 
                && GenSight.LineOfSight(parent.pawn.Position, p.Position, parent.pawn.Map, skipFirstCell: true //可见
                && p != parent.pawn //不是自己
                )).ToList();
                if (probalyFamily.Count > 0) { //存在人选
                    foreach (Pawn p in probalyFamily) { //逐个判断
                        //获得笔记本上的记录
                        ThingComp_writeMemory NoteBook;
                        checkNoteBook(out NoteBook);
                        //已为记忆中的家人则跳过
                        if (rememberFamily.Count > 0) { 
                            bool alreadyFamilyNumber = false;
                            foreach (string familyNumberId in rememberFamily) {
                                if (p.ThingID == familyNumberId) {
                                    alreadyFamilyNumber = true;
                                    break;
                                }
                            }
                            if (alreadyFamilyNumber) { 
                                continue;
                            }
                        }
                        //已为记录中的家人则跳过
                        if (NoteBook != null) {
                            if (NoteBook.FamilyNumbers.Count > 0) {
                                bool alreadyFamilyNumber = false;
                                foreach (string familyNumberId in NoteBook.FamilyNumbers) { 
                                    if (p.ThingID == familyNumberId) {
                                        alreadyFamilyNumber = true;
                                        break;
                                    }   
                                }
                                if (alreadyFamilyNumber) { 
                                    continue;
                                }
                            }
                        }
                        //进行小概率判断决定
                        if (UnityEngine.Random.value > (1 - Props.familyConfirmOdds)) {
                            //认定为家人
                            //不为自己
                            if (p != parent.pawn && p.ThingID != parent.pawn.ThingID) {
                                rememberFamily.AddUnique(p.ThingID);
                            }
                            //如果有装备笔记本，则记录
                            if (NoteBook != null) { 
                                NoteBook.FamilyNumbers.AddUnique(p.ThingID);
                                //笔记本为未记录阵营状态则记录阵营
                                if (NoteBook.theFacton == null) {
                                    NoteBook.theFacton = parent.pawn.Faction;
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 忘记家人，但诺持有记录的笔记则不忘记,一次一个
        /// </summary>
        private void familyNumberForget() {
            if (rememberFamily.Count > 0) {
                for (int i = 0; i < rememberFamily.Count; i++) {
                    string familyNumberID = rememberFamily[i];
                    //概率判定是否可能忘记
                    if (UnityEngine.Random.Range(0f, 1f) < Props.familyForgetOdds) {
                        //获得笔记本上的记录
                        ThingComp_writeMemory NoteBook;
                        checkNoteBook(out NoteBook);
                        //如果笔记本上有记录则不忘记
                        if (NoteBook != null) {
                            bool remeberNumberIsRecordedNumber = false;
                            if (NoteBook.FamilyNumbers.Count > 0) {
                                foreach (string recordedFamilyNumber in NoteBook.FamilyNumbers) {
                                    if (recordedFamilyNumber == familyNumberID) { 
                                        remeberNumberIsRecordedNumber = true;
                                        break;
                                    }
                                }
                            }
                            if (remeberNumberIsRecordedNumber) {
                                continue;
                            }
                        }
                    }
                    //笔记上没记录且中概率，记忆中移除该家人
                    rememberFamily.Remove(familyNumberID);
                    break;
                }
            }
        }
        /// <summary>
        /// 读书
        /// </summary>
        private void readBook() {
            //获得笔记本上的记录
            ThingComp_writeMemory NoteBook;
            checkNoteBook(out NoteBook);
            if (NoteBook != null) {
                //先这样吧，如果发现书与阵营不相同且占比时间更大时，造反就完事了
                if (parent.pawn.Faction == Faction.OfPlayer && NoteBook.theFacton != parent.pawn.Faction && NoteBook.recourdTimes > memoryRecordTimes) {
                    //造反-通常而言这个会更容易被触发
                    parent.pawn.SetFaction(NoteBook.theFacton); //修改回阵营
                    //给点提示
                    ARMIR_language.isThatChinese(out bool yesItIs);
                    if (yesItIs)
                    {
                        Find.LetterStack.ReceiveLetter(
                            "迷迭香反叛".Translate(), // 标题
                            "迷迭香在一本自己曾经记录的笔记本上回忆起了遗失的记忆，并决定离开".Translate(), // 正文
                            LetterDefOf.NegativeEvent, // 信件定义
                            null, // 可选的点击目标
                            NoteBook.theFacton
                        );
                    }
                    else {
                        Find.LetterStack.ReceiveLetter(
                            "Rosmontis Rebellion".Translate(), // 标题
                            "Rosmontis recalls lost memories in a notebook she once kept and decides to leave.".Translate(), // 正文
                            LetterDefOf.NegativeEvent, // 信件定义
                            null, // 可选的点击目标
                            NoteBook.theFacton
                        );
                    }
                    return;
                }
                //书记录了以前的阵营但时间不如在玩家阵营长
                if (NoteBook.theFacton != parent.pawn.Faction && NoteBook.recourdTimes <= memoryRecordTimes) {
                    //伤心-不容易发生的情况
                    parent.pawn.needs.mood.thoughts.memories.TryGainMemory(DefDatabase<ThoughtDef>.GetNamed("ARMIR_sadLostMemory")); //减益
                }
                //遍历记录人家，存在记录但记忆无则记忆
                if (NoteBook.FamilyNumbers != null) {
                    if (rememberFamily != null) {
                        foreach (string recordFamily in NoteBook.FamilyNumbers) {
                            bool existInMemory = false;
                            foreach (string nowFamily in rememberFamily) {
                                if (recordFamily == nowFamily) {
                                    existInMemory = true;
                                }
                            }
                            //如果不存在于记忆中
                            if (!existInMemory) {
                                rememberFamily.Add(recordFamily);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 迷迭香根据环境和家人情况修正心情
        /// </summary>
        private void moodChangeByFamily() {
            //看到活着的心情良好的家人殖民者获得心情增益
            List<Pawn> familyNumber = new List<Pawn>();
            //获得到家人列表
            List<Pawn> pawns = parent.pawn.Map.mapPawns.AllHumanlikeSpawned.Where(p => 
            p.Position.DistanceTo(parent.pawn.Position) < 6 //距离近
            && p.Faction == parent.pawn.Faction //同阵营
            && GenSight.LineOfSight(parent.pawn.Position, p.Position, parent.pawn.Map, skipFirstCell: true) //可见
            && p != parent.pawn).ToList(); //不是自己
            if (pawns.Count > 0) { 
                foreach (Pawn p in pawns) {
                    if (rememberFamily.Count > 0) {
                        foreach (string a in rememberFamily) {
                            //是记忆中的家人
                            if (p.ThingID == a) {
                                //今日是否已见面过
                                bool hadMeet = false;
                                foreach (string b in limitMeetEachDay) {
                                    if (p.ThingID == b) { 
                                        hadMeet = true;
                                    }
                                }
                                if (hadMeet != true) {
                                    familyNumber.Add(p);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            //处理家人列表
            if (familyNumber.Count > 0) {
                foreach (Pawn p in familyNumber) {
                    p.needs.mood.thoughts.memories.TryGainMemory(DefDatabase<ThoughtDef>.GetNamed("ARMIR_beFamily")); //增益
                    parent.pawn.needs.mood.thoughts.memories.TryGainMemory(DefDatabase<ThoughtDef>.GetNamed("ARMIR_familyBe")); //增益
                    limitMeetEachDay.AddUnique(p.ThingID);
                }
            }
        }
        private void recordOnNoteEachDay() {
            //获得笔记本上的记录
            ThingComp_writeMemory NoteBook;
            checkNoteBook(out NoteBook);
            if (NoteBook != null) { 
                NoteBook.recourdTimes = NoteBook.recourdTimes + 1;
            }
            //记录在玩家阵营上的天数
            if (parent.pawn.Faction == Faction.OfPlayer) {
                memoryRecordTimes++;
            }
        }
        private ThingComp_writeMemory checkNoteBook(out ThingComp_writeMemory NoteBook) {
            NoteBook = null;
            //获取装备的武器
            ThingWithComps equippedWeapon = parent.pawn.equipment?.Primary;
            //确认武器是迷迭香的记事本
            if (equippedWeapon != null && equippedWeapon.def == DefDatabase<ThingDef>.GetNamed("ARMIR_Rosmontis_NoteBook"))
            {
                //获取武器的动态数据组件
                ThingComp_writeMemory weaponComp = equippedWeapon.GetComp<ThingComp_writeMemory>();
                if (weaponComp != null)
                {
                    NoteBook = weaponComp;
                    return NoteBook;
                }
            }
            return NoteBook;
        }
        private void Forget() {
            List<Thought_Memory> memories = parent.pawn.needs.mood.thoughts.memories.Memories;
            Thought_Memory removeMemory = null;
            foreach (var m in memories) {
                if (UnityEngine.Random.value > 0.4f) {
                    if (m != null) {
                        removeMemory = m;
                        break;
                    }
                }
            }
            if (removeMemory != null) {
                parent.pawn.needs.mood.thoughts.memories.RemoveMemoriesOfDef(removeMemory.def);
            }
        }
        private void hardRe() {
            //当迷迭香不在玩家阵营且有记忆家人则宁死不屈
            if (parent.pawn.Faction != Faction.OfPlayer && rememberFamily.Count >= 1) {
                parent.pawn.guest.resistance = 15;
            }
        }
        private void ILog() {
            //获得笔记本上的记录
            ThingComp_writeMemory NoteBook;
            checkNoteBook(out NoteBook);
            if (NoteBook != null) {
                Log.Message("[DEBUG] 笔记记录家人" + NoteBook.FamilyNumbers.Count);
                Log.Message("[DEBUG] 笔记记录阵营" + NoteBook.theFacton);
                Log.Message("[DEBUG] 笔记记录所在时间" + NoteBook.recourdTimes);
            }
            else {
                Log.Message("[DEBUG] 迷迭香尚未装备笔记本");
            }
            Log.Message("[DEBUG] 迷迭香在玩家阵营已待天数" + memoryRecordTimes.ToString());
            Log.Message("[DEBUG] 迷迭香已记忆家人" + rememberFamily.Count);
        }

        

    }
}
